package com.xiehua.task.protocol;


import cn.hutool.crypto.digest.DigestUtil;
import com.xiehua.task.prop.XiehuaConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tio.core.intf.Packet;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @date 2018 03-27
 * @author Mr.zhang
 * **/
public class TaskPacket extends Packet {

    private static Logger log = LoggerFactory.getLogger(TaskPacket.class);

    /**
     *
     */
    private static final long serialVersionUID = 1L;

    public static final int HEADER_LENGHT = 70;//消息头的长度 1+1+4+32+32

    public static final String CHARSET = StandardCharsets.UTF_8.name();

    //消息包:
    /***
     *
     * 消息:  [byte]  |   [byte]  |  [4]   | [32]  | [32] | 业务数据
     *      magic num | command | msg leg| cid  | sign | biz data
     *        magicNum = -128<-></->127
     *        salt = uuid
     *        sign = md5([migicNum+salt+bizData)
     *
     * **/
    private byte magicNum;

    private byte type;//消息类型

    private byte[] cid;

    private byte[] sign;

    private byte[] body;

    public TaskPacket(byte magicNum, byte type, String cid) {
        super();
        this.type = type;
        this.magicNum = magicNum;
        this.cid = cid.getBytes();
    }

    public TaskPacket(byte magicNum, byte type, byte[] cid, byte[] sign) {
        super();
        this.magicNum = magicNum;
        this.type = type;
        this.cid = cid;
        this.sign = sign;
    }

    public TaskPacket(byte type, String cid) {
        super();
        this.type = type;
        magicNum =  genMagicNum();
        this.cid = cid.getBytes();
    }


    private TaskPacket(){}

    public static TaskPacket heartbeatPacket(){
        Map<String,String> configMap = XiehuaConfig.getInstance();
        TaskPacket heartbeatPacket = new TaskPacket(Type.HEART_BEAT_REQ, configMap.get(XiehuaConfig.KEY_CLIENT_CID));
        heartbeatPacket.signData(null, configMap.get(XiehuaConfig.KEY_CLIENT_SECRET_KEY));
        return heartbeatPacket;
    }

    public static TaskPacket bindClientPacket(String bizDate) throws UnsupportedEncodingException {
        Map<String,String> configMap = XiehuaConfig.getInstance();
        TaskPacket bindClientPacket = new TaskPacket(Type.BIND_CLIENT, configMap.get(XiehuaConfig.KEY_CLIENT_CID));
        bindClientPacket.signData(bizDate, configMap.get(XiehuaConfig.KEY_CLIENT_SECRET_KEY));
        bindClientPacket.setBody(bizDate.getBytes(CHARSET));
        return bindClientPacket;
    }

    public static TaskPacket broadcastPacket(String data) throws UnsupportedEncodingException {
        TaskPacket broadcastPacket = new TaskPacket(Type.BROADCAST, UUID.randomUUID().toString().replace("-",""));
        if(data != null){
            broadcastPacket.body = data.getBytes(CHARSET);
            broadcastPacket.signData(data, UUID.randomUUID().toString().replace("-",""));
        }else{
            broadcastPacket.signData(null, UUID.randomUUID().toString().replace("-",""));
        }
        return broadcastPacket;
    }

    public byte getMagicNum() {
        return magicNum;
    }

    public byte[] getCid() {
        return cid;
    }

    public String getClientId(){
        if (cid != null){
            return new String(cid);
        }
        return null;
    }

    public String getBizData(){
        if(body != null){
            return new String(body);
        }
        return null;
    }

    public String getSignData(){
        if(sign != null){
            return new String(sign);
        }
        return null;
    }

    public byte[] getSign() {
        return sign;
    }

    /**
     * @return the body
     */
    public byte[] getBody() {
        return body;
    }

    /**
     * @return the type
     */
    public byte getType() {
        return type;
    }

    @Override
    public String logstr() {
        return "" + type;
    }

    /**
     * @param body the body to set
     */
    public void setBody(byte[] body) {
        this.body = body;
    }

    /**
     * @param type the type to set
     */
    public void setType(byte type) {
        this.type = type;
    }

    /***
     * gen magic num
     * **/
    public byte genMagicNum(){
        Integer randNumber = new Random().nextInt(Byte.MAX_VALUE - Byte.MIN_VALUE + 1) + Byte.MIN_VALUE;
        return randNumber.byteValue();
    }

    public void signData(String bizData,String secretKey){
        if(bizData == null || bizData.equals("")){
            log.warn("业务数据为空");
            sign = DigestUtil.md5Hex(Byte.toString(magicNum).concat(secretKey)).getBytes();
            return ;
        }
        sign = DigestUtil.md5Hex(Byte.toString(magicNum).concat(secretKey).concat(bizData)).getBytes();
        return ;
    }

    public String signData(String secretKey){
        if(getBizData() != null){
            return DigestUtil.md5Hex(Byte.toString(magicNum).concat(secretKey).concat(getBizData()));
        }
        log.warn("业务数据为空");
        return DigestUtil.md5Hex(Byte.toString(magicNum).concat(secretKey));
    }

    // 使用 Arrays.copyOf() 方法,但要在 java6++版本中
    public static  String[] concat(String[] first, String[] second) {
        String[] result = Arrays.copyOf(first, first.length + second.length);
        System.arraycopy(second, 0, result, first.length, second.length);
        return result;
    }



    public static void main(String[] args) {
        String uuid = UUID.randomUUID().toString().replace("-","");
        System.out.println(uuid.getBytes().length);
        System.out.println(Byte.toString(Byte.MIN_VALUE));
        System.out.println(DigestUtil.md5("123").length);
    }


}
